module example (                //模块开始 模块名字
    input wire sys_clk ,        //输入时钟信号
    input wire sys_rst_n ,      //输入复位信号
    inout wire sda,             //输入输出信号 比如I2C协议中的sda引脚既可以作为数据输出也可以作为数据的输入

    output wire pro_flag        //输出信号
);

/****************************************************************/
/*只有输入信号，是不可能直接生成输出信号的，我们需要一些变量和参数对输入信号进行一些处理*/

//而变量呢又分为两种类型：1、线网型变量；2、寄存器型变量
//测试git用的
//线网型变量
wire [0:0]  flag ;      //可以看成直接连接，在可综合的逻辑中被映射为一条真实存在的物理连线
                        //[0:0]代表着变量的的宽度，或者这个变量需要几条线路来传输
                        //线网型还有其他数据类型，包括 wand，wor，wri，triand，trior，trireg 等

//寄存器型变量
reg [7:0] cnt;          //对某一时间点的状态进行保存的功能，在可综合的逻辑中被映射为一个真实的物理寄存器

reg [3:0]      counter ;    //声明4bit位宽的寄存器counter
wire [32-1:0]  gpio_data;   //声明32bit位宽的线型变量gpio_data
wire [8:2]     addr ;       //声明7bit位宽的线型变量addr，位宽范围为8:2
reg [0:31]     data ;       //声明32bit位宽的寄存器变量data, 最高有效位为0


/****************************************************************/
/*参数*/
parameter CNT_MAX = 100;        //我们可以在顶层文件，通过实例化对此功能模块的参数进行修改
localparam CNT_MAX = 100;       //只能在模块内部使用，不能实例化

/****************************************************************/
/*常量*/
8'd171  //代表 位宽是8bit，十进制的171

//十进制('d 或 'D)，十六进制('h 或 'H)，二进制（'b 或 'B），八进制（'o 或 'O）

4'b1011         // 4bit 数值
32'h3022_c0de   // 32bit 的数值

//负数
-6'd15  
-15

//科学计数法
1.2e4         //大小为12000
1_0001e4      //大小为100010000
1E-3          //大小为0.001

//字符串表示方法
reg [0: 14*8-1]       str ;
initial begin
    str = "www.runoob.com";
end  


/****************************************************************/
/*赋值*/
//阻塞赋值 = “每条语句执行完成之后才会执行下一条语句”
a = 1;
b = 2;
c = 3;
begin
    a = b;
    c = a;
end
a = 2;
b = 2;
c = 2;

//非阻塞赋值 <= ”语句之间是并行执行的“
//非阻塞赋值的赋值号用“<=”表示，对应的电路结构往往与触发沿有关系，只有在触发沿的时刻才能进行非阻塞赋值。
//它的操作可以看作为两个步骤的过程:在赋值开始时刻计算赋值号右边的语句。在赋值结束时刻，更新赋值号左边的语句。
//在计算非阻塞语句赋值号右边的语句和更新赋值号左边的语句期间，允许其他的Verilog语同时进行操作。
//非阻塞操作只能用于对寄存器类型变量进行赋值，因此只能用于“initial”和“always”块中，不允许用于连续赋值assign。
a = 1;
b = 2;
c = 3;
begin
    a <= b;
    c <= a;
end
a = 2;
b = 2;
c = 1;



/****************************************************************/
/*always语句*/
always (posedge sys_clk or negedge sys_rst_n)
    if (sys_rst_n == 1'b0)  
        cnt <= 8’d0;
    else if(cnt == CNT_MAX)
        cnt <= CNT_MAX;
    else 
        cnt <= cnt + 8'd1;


/****************************************************************/
/*assign语句*/    
assign pro_flag = (cnt==CNT_MAX) ? 1'b1 : 1'bo;

//assign是Verilog语言中一种用于连接线路的语句，用于把输出线路的值赋给输入线路。它的格式为：“assign 输出线路 = 表达式”。 
//例如：
assign A = B + C;




/****************************************************************/
/*模块实例化*/ 
//实例化可以理解为 调用函数。
//用于创建复杂的硬件系统，允许客户把一个模块放在另一个模块中，可以用来创造复杂的系统
example
#(
    .CNT_MAX    (8'd100)    //实例化是参数可修改
)

endmodule                       //模块结束



/****************************************************************/
/*算数运算符*/
//  + - * /  没什么特殊的，注意 * / 一般不用

/****************************************************************/
/*归约运算符
& 操作符有两种用途，既可以作为一元运算符（只有一个参与运算的量），也可以二元运算符
*/

//&当一元运算符时，表示规约与
&4'b1111 = 1&1&1&1 = 1'b1
&4'b1101 = 1&1&0&1 = 1'b0

//&当一元运算符时，表示按位与
4'b1010 & 4'b0101 = 4'b0000
4'b1101 & 4'b1111 = 4'b1101

/****************************************************************/
/*逻辑运算符*/
a=4'ha;
b=4'd0;
c=a && b;//c的值位0
//逻辑或|| 逻辑相等== 逻辑不等!=

/****************************************************************/
/*位拼接运算符*/
//将一个8bit的a，3bit的b，5bit的c按顺序拼接成一个16位的d
d = {a, b, c};

/****************************************************************/
/*系统函数*/
//Verlig语言中预先定义了一些任务和函数，用来完成一些特殊的功能，它们被称为系统任务和系统函数，这些函数大多只能在Testbench仿真中使用


`timescale 1ns/1ns         //时间尺度预编译指令 时间单位/时间精度
//时间单位和时间精度由值1、10、100以及单位s、ms、us、ns、ps、fs组成
//时间单位：定义仿真过程所有与时间相关量的单位
//仿真中使用  #数字 ，表示延时相应单位时间单位的时间，这里就是10ns
//时间精度：决定时间相关量的精度及仿真仿真显示的最小刻度
`timescale 1ns/10ps        //精度0.01，#10.11 表示延时10110ps

$display            //打印信息，自动换行
$display("%b+%b=%d",a ,b ,c);


$write              //打印信息，不会自己换行
$strobe             //输出打印信息，但只在最后执行
$monitor            //用于监控变量的变化
$stop               //暂停仿真
$finish             //结束仿真
$time               //时间函数，返回当前64位当前仿真时间，
$random             //用于产生随机数
$readmemb           //用于读二进制文件函数
$readmemh           //用于读十六进制文件函数

